<script setup lang="ts">
import RoomStatus from './components/RoomStatus.vue'
import RoomAction from './components/RoomAction.vue'
import RoomMessage from './components/RoomMessage.vue'
import type { Socket } from 'socket.io-client'
import { io } from 'socket.io-client'
import { nextTick, onMounted, onUnmounted, ref } from 'vue'
import { baseURL } from '@/utils/request'
import { useUserStore } from '@/stores'
import { useRoute } from 'vue-router'
import type { TimeMessages, Message } from '@/types/room'
import { MsgType, OrderType } from '@/enums'
import { getConsultOrderDetail } from '@/services/consult'
import type { ConsultOrderItem, Image } from '@/types/consult'
import dayjs from 'dayjs'
import { showToast } from 'vant'
import { provide } from 'vue'

const userStore = useUserStore()
const route = useRoute()
const list = ref<Message[]>([]) // const list: Ref<Message[]> = ref([])
const loading = ref<boolean>(false)
// 订单详情
const orderDetail = ref<ConsultOrderItem>()

provide('orderDetail', orderDetail)

// 将list里面的未评价消息改成已评价消息
const changeToCardEva = (score: number) => {
  // 在list中先找到未评价的消息 23
  const CardEvaFormMsg = list.value.find(
    (item) => item.msgType === MsgType.CardEvaForm
  )
  if (CardEvaFormMsg) {
    // 找到之后，将它的msgType改成已评价的
    CardEvaFormMsg.msgType = MsgType.CardEva
    CardEvaFormMsg.msg.evaluateDoc = { score }
  }
}
provide('changeToCardEva', changeToCardEva)

let socket: Socket

onUnmounted(() => {
  socket.close()
  console.log('关闭连接')
})

const loadOrderDetail = async () => {
  let { data } = await getConsultOrderDetail(route.query.orderId as string)
  orderDetail.value = data
}

// 建立连接
socket = io(baseURL, {
  // 配置token
  auth: {
    token: 'Bearer ' + userStore.userinfo?.token
  },
  // 配置查询参数 需要订单编号
  query: {
    orderId: route.query.orderId
  }
})

// 发送消息
const sendMsg = (msg: string) => {
  socket.emit('sendChatMsg', {
    // 患者的id
    from: userStore.userinfo?.id,
    // 医生的id
    to: orderDetail.value?.docInfo?.id,
    msg: {
      content: msg
    },
    msgType: MsgType.MsgText
  })
}

const sendImg = (img: Image) => {
  socket.emit('sendChatMsg', {
    // 患者的id
    from: userStore.userinfo?.id,
    // 医生的id
    to: orderDetail.value?.docInfo?.id,
    msg: {
      picture: img
    },
    msgType: MsgType.MsgImage
  })
}
const currentTime = ref(dayjs().format('YYYY-MM-DD HH:mm:ss'))
// 下拉刷新
const onRefresh = () => {
  // 第一次下拉的时候获取的是最新的时间 这里这是触发一个下拉获取最新数据的动作，服务器监听到这个动作之后，又会重新发送一个chatMsgList事件。
  // 当再次下来的时候，应该以上次获取的时间为准，去获取更早的数据
  socket.emit('getChatMsgList', 20, currentTime.value, route.query.orderId)
}

// 是否是第一次渲染
const firstRender = ref<boolean>(true)

onMounted(() => {
  loadOrderDetail()

  // 渲染的聊天记录 列表

  socket.on('chatMsgList', ({ data }: { data: TimeMessages[] }) => {
    // 需要渲染的聊天历史数据是一个数组，它是放在data中的items中的。 [...data.items]，除了这个以外，我们还需要把时间也做成一个历史记录，放到数组中，然后渲染渲染出来。 [{时间信息记录对象}, ...data.items]
    // 定义一个数组，临时存放聊天记录
    const arrMsg: Message[] = []
    // 判断是否有更多数据
    if (!data.length) {
      loading.value = false
      return showToast('没有更多数据了！')
    }
    // 发完请求，利用响应的时间，作为下次下拉刷新发请求的参数
    currentTime.value = data[0].createTime
    data.forEach((msg) => {
      //构建一个时间消息对象 必须要有 id msgType createTime msg
      let timeMsg = {
        id: msg.createTime,
        msgType: MsgType.Notify,
        createTime: msg.createTime,
        msg: {
          content: msg.createTime
        }
      }
      arrMsg.push(timeMsg, ...msg.items)
    })
    // 将数据添加到list的前面 用unshift
    list.value.unshift(...arrMsg)
    loading.value = false
    nextTick(() => {
      // 如果是第一次渲染，那么就滚动到底部
      if (firstRender.value) {
        socket.emit('updateMsgStatus', arrMsg[arrMsg.length - 1].id)
        window.scrollTo(0, document.body.scrollHeight)
        // 将firstRender设置为false
        firstRender.value = false
      }
    })
  })

  socket.on('connect', () => {
    // 当对话链接时数据清空
    list.value = []
    console.log('连接成功了')
  })
  socket.on('disconnect', () => {
    console.log('断开连接了')
  })
  socket.on('error', (err) => {
    console.log('连接错误', err)
  })
  // 监听状态改变
  socket.on('statusChange', () => {
    loadOrderDetail()
  })
  // 患者接收聊天信息
  socket.on('receiveChatMsg', async (msg: Message) => {
    list.value.push(msg)
    // 滚动到底部
    await nextTick() // dom的操作必须要等到页面更新完毕之后执行才有效果 也可以用setTimeout来解决
    socket.emit('updateMsgStatus', msg.id)
    window.scrollTo(0, document.body.scrollHeight)
  })
})
</script>

<template>
  <div class="room-page">
    <cp-nav-bar title="问诊室" :right-text="''" />
    <room-status
      :status="orderDetail?.status"
      :countdown="orderDetail?.countdown"
    ></room-status>
    <van-pull-refresh v-model="loading" @refresh="onRefresh">
      <room-message
        v-for="item in list"
        :key="item.id"
        :item="item"
      ></room-message>
    </van-pull-refresh>
    <!-- 如果问诊的状态不是咨询中，那就应该禁用输入的操作 -->
    <room-action
      :disabled="orderDetail?.status !== OrderType.ConsultChat"
      @onSendMsg="sendMsg"
      @onSendImg="sendImg"
    ></room-action>
  </div>
</template>

<style lang="scss" scoped>
.room-page {
  padding-top: 90px;
  padding-bottom: 60px;
  min-height: 100vh;
  box-sizing: border-box;
  background-color: var(--cp-bg);
  .van-pull-refresh {
    width: 100%;
    min-height: calc(100vh - 150px);
  }
}
</style>
